package com.mp.ipm2020.mbg.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.mp.ipm2020.mbg.bo.AdminUserDetails;
import com.mp.ipm2020.mbg.dao.UserRoleRelationDao;
import com.mp.ipm2020.mbg.dto.UpdateUserPasswordParam;
import com.mp.ipm2020.mbg.dto.UserParam;
import com.mp.ipm2020.mbg.mapper.UserLoginLogMapper;
import com.mp.ipm2020.mbg.mapper.UserRoleRelationMapper;
import com.mp.ipm2020.mbg.model.*;
import com.mp.ipm2020.mbg.mapper.UserMapper;
import com.mp.ipm2020.mbg.service.UserRoleRelationService;
import com.mp.ipm2020.mbg.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mp.ipm2020.security.util.JwtTokenUtil;
import org.omg.CORBA.ULongLongSeqHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author adidasshe
 * @since 2020-05-08
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserLoginLogMapper userLoginLogMapper;
    @Autowired
    private UserRoleRelationDao userRoleRelationDao;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private UserRoleRelationService userRoleRelationService;
    //密码编码器
//    @Bean
//    public PasswordEncoder passwordEncoder() {
//        return new BCryptPasswordEncoder();
//    }

    @Override
    public User getUserByUsername(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        List<User> userList = userMapper.selectList(wrapper);
        if (userList != null && userList.size() > 0) {
            return userList.get(0);
        }
        return null;
    }

    @Override
    public User register(UserParam userParam) {
        User user = new User();
        BeanUtils.copyProperties(userParam, user);
        user.setCreateTime(new Date());
        user.setPassword("123456");
//        user.setStatus(1);
        //查询同名用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .eq("username", user.getUsername());
        List<User> userList = userMapper.selectList(wrapper);
        if (userList.size() > 0) {
            return null;
        }
        //将密码做加密操作,默认密码123456
        String encode = passwordEncoder.encode(user.getPassword());
        user.setPassword(encode);
        userMapper.insert(user);
        return user;
    }

    @Override
    public String login(String username, String password) {
        String token = null;
        //密码需要客户端加密后传递
        try {
            UserDetails userDetails = loadUserByUsername(username);
            if (!passwordEncoder.matches(password, userDetails.getPassword())) {
                throw new BadCredentialsException("密码不正确");
            }
            System.out.println("error");
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
                    null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails);
            updateLoginTimeByUsername(username);
            insertLoginLog(username);
        } catch (AuthenticationException e) {
//            LOGGER.warn("登录异常:{}", e.getMessage());
        }
        return token;
    }

    /**
     * 添加登录记录
     *
     * @param username 用户名
     */
    private void insertLoginLog(String username) {
        User user = getUserByUsername(username);
        if (user == null) return;
        UserLoginLog loginLog = new UserLoginLog();
        loginLog.setUserId(user.getId());
        loginLog.setCreateTime(new Date());
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        loginLog.setIp(request.getRemoteAddr());
        userLoginLogMapper.insert(loginLog);
    }

    /**
     * 根据用户名修改登录时间
     */
    private void updateLoginTimeByUsername(String username) {
        System.out.println(username);
        User user = new User();
        user.setLoginTime(new Date());
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("username", username);
        userMapper.update(user, wrapper);
    }

    @Override
    public String refreshToken(String oldToken) {
        return jwtTokenUtil.refreshHeadToken(oldToken);
    }


    @Override
    public List<User> list(String keyword, Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(keyword)) {
            wrapper
                    .like("username", keyword)
                    .or()
                    .like("name", keyword)
                    .or()
                    .like("phone", keyword);
        }
        return userMapper.selectList(wrapper);

    }

    @Override
    public boolean updateStatusById(Long id, User user) {
        //防止修改用户状态时候连带自动更新登录时间为空
        if (user.getLoginTime() == null) {
            User setUser = userMapper.selectById(id);
            user.setLoginTime(setUser.getLoginTime());
        }
        return updateById(user);
    }


    @Override
    public boolean updateRole(Long userId, List<Long> roleIds) {
        boolean count = false;
        //删除原来的关系
        QueryWrapper<UserRoleRelation> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
//        userRoleRelationMapper.delete(wrapper);
        userRoleRelationService.remove(wrapper);
        if (!CollectionUtils.isEmpty(roleIds)) {
            List<UserRoleRelation> list = new ArrayList<>();
            for (Long roleId : roleIds) {
                UserRoleRelation roleRelation = new UserRoleRelation();
                roleRelation.setUserId(userId);
                roleRelation.setRoleId(roleId);
                list.add(roleRelation);
            }
            count = userRoleRelationService.saveBatch(list);
            return count;
        }
        return count;
    }

    @Override
    public List<Role> getRoleList(Long userId) {
        return userRoleRelationDao.getRoleList(userId);
    }

    @Override
    public List<Resource> getResourceList(Long userId) {
        return userRoleRelationDao.getResourceList(userId);
    }


    @Override
    public int updatePassword(UpdateUserPasswordParam updatePasswordParam) {
        if (StrUtil.isEmpty(updatePasswordParam.getUsername())
                || StrUtil.isEmpty(updatePasswordParam.getOldPassword())
                || StrUtil.isEmpty(updatePasswordParam.getNewPassword())) {
            return -1;
        }
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", updatePasswordParam.getUsername());
        List<User> userList = userMapper.selectList(wrapper);
        if (CollUtil.isEmpty(userList)) {
            return -2;
        }
        User user = userList.get(0);
        if (!passwordEncoder.matches(updatePasswordParam.getOldPassword(), user.getPassword())) {
            return -3;
        }
        user.setPassword(passwordEncoder.encode(updatePasswordParam.getNewPassword()));
        userMapper.updateById(user);
        return 1;
    }

    /**
     * 获取预置的用户信息
     *
     * @param username
     * @return 包含了用户名、密码、权限列表等基础的用户信息属性
     */
    @Override
    public UserDetails loadUserByUsername(String username) {
        //从数据库获取用户信息
        User user = getUserByUsername(username);
        if (user != null) {
            //如果用户状态不可用，抛出异常
            if (user.getStatus() == 1) {
                List<Resource> resourceList = getResourceList(user.getId());
                return new AdminUserDetails(user, resourceList);
            }
        }
        throw new UsernameNotFoundException("用户名或密码错误");

    }
}
